package com.xquant.pricing.systerm.service.task;

import com.xquant.pricing.calc.entity.TaskLog;
import com.xquant.pricing.systerm.service.TaskService;
import com.xquant.pricing.utils.DateUtils;
import com.xquant.pricing.utils.SpringBeanUtils;
import com.xquant.common.engine.xPP.cxf.NotifyDataFacade;
import com.xquant.common.engine.xPP.cxf.XQuantPPService;
import com.xquant.common.engine.xPP.cxf.XQuantPPStub;
import com.xquant.common.engine.xPP.cxf.webservice.RunTask;
import com.xquant.common.engine.xPP.cxf.webservice.RunTaskResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.RemoteException;
import java.text.MessageFormat;
import java.util.concurrent.*;

/**
 * @author B946
 * @date 2021/1/22 14:28
 * @description:
 */
public class JobScheduledTimerTask implements Runnable {

    private static volatile boolean isDong = false;
    private static Logger logger = LoggerFactory.getLogger(JobScheduledTimerTask.class);

    private static ExecutorService exec = Executors.newFixedThreadPool(1);

    @Override
    public void run() {
        if (isDong) {
            return;
        }
        BlockingQueue<TaskEntity> queue = JobScheduledPools.getPools();

        TaskEntity taskEntity = queue.poll();
        if (taskEntity == null) {
            return;
        }

        try {
            isDong = true;
            Future future = JobScheduledPools.exec.submit(getTask(taskEntity));
            future.get();

        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            isDong = false;
        }
    }


    private Callable<Object> getTask(TaskEntity taskEntity) {
        return new Callable<Object>() {

            @Override
            public Object call() throws Exception {
                runPPTask(taskEntity);
                return true;
            }
        };
    }

    private static void runPPTask(final TaskEntity taskEntity) {

        String executeDate = taskEntity.getBaseDate();
        if (executeDate == null) {
            return;
        }

        TaskLog taskLog = new TaskLog();
        TaskService taskLogService = SpringBeanUtils.getBean(TaskService.class);
        XQuantPPService ppService = SpringBeanUtils.getBean(XQuantPPService.class);
        logger.info(MessageFormat.format("任务 {0} 开始!,任务参数：{1}", taskEntity.getJobName(), taskEntity.getContext()));
        XQuantPPStub stub = null;
        try {
            // 插入任务日志
            taskLog.setTaskName(taskEntity.getJobName());
            taskLog.setContext(taskEntity.getContext());
            taskLog.setStatus(0);
            taskLog.setStartTime(DateUtils.getCurrentDateTimeOther());
            taskLogService.addTaskLog(taskLog);
            RunTask runTask = new RunTask();
            runTask.setParam(new String(taskEntity.getContext().getBytes("ISO-8859-1"), "ASCII"));

            stub = ppService.borrowStub();
            RunTaskResponse ret = stub.runTask(runTask);
            cleanPPCache(taskEntity.getContext());


            // 更新任务日志状态
            taskLog.setStatus(1);
            taskLog.setResult("计算任务计算成功");
            logger.info(MessageFormat.format("任务 {0} 结束!", taskEntity.getJobName()));
            if (ret.getRunTaskResult().getErrorCode() < 0) {
                taskLog.setStatus(2);
                taskLog.setResult("计算任务计算失败：" + ret.getRunTaskResult().getErrorMsg());
                logger.error(MessageFormat.format("任务 {0} 失败，失败信息：!", taskEntity.getJobName(), ret.getRunTaskResult().getErrorMsg()));
            }
        } catch (RemoteException ex) {
            taskLog.setStatus(2);
            taskLog.setResult("连接计算服务失败！");
            logger.error(MessageFormat.format("任务 {0} 失败!，原因：连接计算服务失败！", taskEntity.getJobName()));
            if (stub != null) {
                ppService.setTimeOut(stub);
            }
        } catch (Exception ex) {
            taskLog.setStatus(2);
            taskLog.setResult(ex.toString());
            logger.error(MessageFormat.format("任务 {0} 失败!，原因：{1}", taskEntity.getJobName(), ex.getMessage()));
        } finally {
            if (stub != null) {
                ppService.returnStub(stub);
            }
            taskLog.setFinishTime(DateUtils.getCurrentDateTimeOther());
            taskLogService.updateTaskLog(taskLog);
        }
    }

    private static void cleanPPCache(String context) {
        NotifyDataFacade notifyDataFacade = null;
        //违约率
        if (context.indexOf("<DefCurve>") != -1) {
            notifyDataFacade = SpringBeanUtils.getBean(NotifyDataFacade.class);
            notifyDataFacade.notifyDefYieldCurveTS();
            //分红率
        } else if (context.indexOf("<DivYield") != -1) {
            notifyDataFacade = SpringBeanUtils.getBean(NotifyDataFacade.class);
            notifyDataFacade.notifyDivYieldCurveTS();
            //波动率
        } else if (context.indexOf("<VolSurface") != -1) {
            notifyDataFacade = SpringBeanUtils.getBean(NotifyDataFacade.class);
            notifyDataFacade.notifyVolSurfaceTS();
            //利率曲线
        } else if (context.indexOf("<IRCurve>") != -1) {
            notifyDataFacade = SpringBeanUtils.getBean(NotifyDataFacade.class);
            notifyDataFacade.notifyYieldCurveTS();
        }
    }
}
